//===============================================================================
// Microsoft patterns & practices Enterprise Library Contribution
// Resource Application Block
//===============================================================================

using System;
using System.Configuration;
using System.Reflection;
using System.ComponentModel;
using System.Resources;
using System.Globalization;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using Microsoft.Practices.EnterpriseLibrary.Data;

namespace EntLibContrib.Resource.Managers
{
	/// <summary>
	/// Custom resource manager for managing resources held on a database
	/// </summary>
	public class DataResourceManager : ExtendedComponentResourceManager
	{
		#region Fields
		private Database database;
		private string baseName;
		#endregion

		#region Construction
		/// <summary>
		/// Initializes a new instance of the <see cref="T:DataResourceManager"/> class.
		/// </summary>
		/// <param name="database">The database.</param>
		public DataResourceManager(Database database)
		{
			Initialize(database, String.Empty);
		}

		/// <summary>
		/// Initializes a new instance of the <see cref="DataResourceManager"/> class.
		/// </summary>
		/// <param name="database">The database.</param>
		/// <param name="baseName">base name for the set of resources.</param>
		public DataResourceManager(Database database, string baseName)
		{
			Initialize(database, baseName);
		}

		/// <summary>
		/// Initializes a new instance of the <see cref="DataResourceManager"/> class.
		/// </summary>
		/// <param name="database">The database.</param>
		/// <param name="resourceType">Type of the resource.</param>
		public DataResourceManager(Database database, Type resourceType)
		{
			if (database == null)
				throw new ArgumentNullException("database");

			if (resourceType == null)
				throw new ArgumentNullException("resourceType");

			Initialize(database, resourceType.Name);
		}
		#endregion

		#region Protected Methods
		/// <summary>
		/// Initializes the data resource manager.
		/// </summary>
		/// <param name="database">The database.</param>
		/// <param name="baseName">base name for the set of resources.</param>
		protected virtual void Initialize(Database database, string baseName)
		{
			this.database = database;
			this.baseName = baseName;
			this.ResourceSets = new Hashtable();
		}

		/// <summary>
		/// Provides the implementation for finding a <see cref="T:System.Resources.ResourceSet"></see>.
		/// </summary>
		/// <param name="culture">The <see cref="T:System.Globalization.CultureInfo"></see> to look for.</param>
		/// <param name="createIfNotExists">If true and if the <see cref="T:System.Resources.ResourceSet"></see> has not been loaded yet, load it.</param>
		/// <param name="tryParents">If the <see cref="T:System.Resources.ResourceSet"></see> cannot be loaded, try parent <see cref="T:System.Globalization.CultureInfo"></see> objects to see if they exist.</param>
		/// <returns>
		/// The specified <see cref="T:System.Resources.ResourceSet"></see>.
		/// </returns>
		/// <exception cref="T:System.Resources.MissingManifestResourceException">The database contains no resources or fallback resources for the culture given and it is required to look up a resource. </exception>
		protected override ResourceSet InternalGetResourceSet (CultureInfo culture, bool createIfNotExists, bool tryParents)
		{
			DataResourceSet resourceSet = null;

			// check the resource set cache first
			if (ResourceSets.Contains(culture.Name))
				resourceSet = (DataResourceSet)ResourceSets[culture.Name];
			else
			{
				// create a new resource set
				resourceSet = new DataResourceSet(database, baseName, culture);
				// check the number of resources returned
				if (resourceSet.Count == 0)
				{
					// try the parent culture if not already at the invariant culture
					if (tryParents)
					{
						if (culture.Equals(CultureInfo.InvariantCulture))
							throw new MissingManifestResourceException(database.ConnectionStringWithoutCredentials + Environment.NewLine + this.baseName + Environment.NewLine + culture.Name);

						// do a recursive call on this method with the parent culture
						resourceSet = this.InternalGetResourceSet(culture.Parent, createIfNotExists, tryParents) as DataResourceSet;
					}
				}
				else
				{
					// only cache the resource if the createIfNotExists flag is set
					if (createIfNotExists)
						ResourceSets.Add(culture.Name, resourceSet);
				}
			}
			return resourceSet;
		}
		#endregion
	}
}
